/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package server.network;

import java.io.*;
import java.net.*;
import com.cse.p2p.common.*;
import com.cse.p2p.database.*;
import com.cse.p2p.hash.*;
import com.cse.p2p.localfile.*;
import com.cse.p2p.parser.*;
import java.util.HashMap;
import server.dicfile.DicFileGenerating;
import server.meta.UploadMeta;
import serverside.DataServerSide;

/**
 *
 * @author TuyetNgan
 */
public class ServerControlTask_Server extends Thread {

	private DataServerSide dataThread;
	private Socket socket = null;
	private PrintStream out = null;
	private BufferedReader in = null;
	private BufferedReader infromScreen = null;
	private Integer ID;
	int defaultPortDataReceive = 2000;
	int defaultPortDataSend = 2001;
	private FileMetadata file_mete_data;
	private DicFileGenerating dic;
	private HashMap<String, String> peerOnline;

	public ServerControlTask_Server( Socket s, int id, HashMap st, DataServerSide dThread ) {
		this.dataThread = dThread;
		this.socket = s;
		this.peerOnline = st;
		this.ID = id;
	}

	public void newChat() {
		try {
			out = new PrintStream( socket.getOutputStream() );
			in = new BufferedReader( new InputStreamReader( socket.getInputStream() ) );
			infromScreen = new BufferedReader( new InputStreamReader( System.in ) );
		}
		catch ( IOException e ) {
		}
	}

	public void closeConnection() {
		try {
			out.close();
			in.close();
			infromScreen.close();
			socket.close();
		}
		catch ( IOException e ) {
		}

	}

	@Override
	public void run() {
		try {
			newChat();
			System.out.println( "New client connected: " + socket.getRemoteSocketAddress().toString() + " on port " + socket.getPort() );
//                String userName = in.readLine();
			String mess;

			while ( ( mess = in.readLine() ) != null ) {
				Message message = Message.fromString( mess );
				int typeOfProtocol = message.getType();
				String data = message.getData();
				switch ( typeOfProtocol ) {

					// client register first
					case Message.MsgType.REQ_REG_NICK:
						String userName = data;
						peerOnline.put( userName, this.socket.getRemoteSocketAddress().toString() );
						System.out.println( "PeerOnline " + userName );
						break;

					// client get the list of all available pieces of a file
					case Message.MsgType.REQ_FOR_AVAI_PIECES: {
						String fileID = data;
						// call thread peer to collect info -> fileID
						for ( String string : peerOnline.keySet() ) {
							String IPadd = peerOnline.get( string );
						}

						break;
					}
					// server collect the info of all available pieces of a file
					case Message.MsgType.RES_VRF_ALL_PIECES: {
						String peer_info = data;
						/* concatanate all peer online */
						// TODO : Networking
                            /* return List<PeerInfo> */
						break;
					}

					// client ask for the permision of uploading a file
					case Message.MsgType.REQ_UP_HOST_FILE: {
						System.out.println( socket.getRemoteSocketAddress().toString() + ":" + socket.getPort() + " request to upload a new file!" );
						file_mete_data = FileMetadata.fromString( data );
						/* analyzing file */
						// Call LocalFile to check Disk
						// TO DO ...
						String currentPath = ( new File( "." ) ).getAbsolutePath();
						String defaultFolder = currentPath + File.separatorChar + "storage";

						File defaultStorageDir = new File( defaultFolder );
						if ( !defaultStorageDir.exists() ) {
							defaultStorageDir.mkdir();
						}

						File newFile = new File( defaultFolder + File.separatorChar + file_mete_data.getFileName() + "-" + Long.toString( System.currentTimeMillis() / 1000 ) );
						System.out.println( "New file will be created as " + newFile.getAbsolutePath() );

						out.println( ( new Message( Message.Command.PUT, Message.Keyword.UP, "OK" ) ).toString() );
						out.flush();

						String remoteAddr = socket.getRemoteSocketAddress().toString();
						dataThread.registerNewUpload( remoteAddr.substring( 1, remoteAddr.lastIndexOf( ":" ) ),
													  new UploadMeta( newFile.getAbsolutePath(), file_mete_data, this ) );

						break;
					}

					// client response receive message upload file is finished
					case Message.MsgType.RES_UP_DIC_FILE: {
						if ( data.equals( "OK" ) ) {
							System.out.println( "Client response OK" );
							System.out.println( "Complete the Dicfile generating routine with " + socket.getRemoteSocketAddress().toString() );
//							/* send DicFile back to client */
//							//dic.getPath
//							//example
//							File dicf = new File( "C://dicfile.txt" );
////                                Thread t = new Thread(new SendData(dicf, defaultPortDataSend));
////                                t.sleep(1000);
////                                t.start();
////                                while(t.isAlive());
						}
						else if ( data.equals( "NONE" ) ) {
							// never happen this case
							System.out.println( "Send again!" );

						}
						else { // error
							System.out.println( "ERROR : RES_UP_DIC_FILE" );
						}
						break;
					}

					// client response for the dicfile transfering
					case Message.MsgType.RES_FILE_TRANSFER: {

						if ( data.equals( "OK" ) ) {
							System.out.print( "Finish!" );
						}
						else if ( data.equals( "NONE" ) ) {
							/* remember client didnot receive dicfile */
							/* if client online , send again*/

							/* send and wait for signal from client accept DicFile */
							Message messSend2 = new Message( "GET", "UP", "DIC" );
							out.println( messSend2.toString() );
						}
						else {
							System.out.println( "ERROR : RES_FILE_TRANSFER" );
						}
						break;
					}


				}
			}
		}
		catch ( Exception exc ) {
			System.err.println( exc.getMessage() );
			exc.printStackTrace();
		}
	}

	public void sendDicFile( DicFile dicFile ) {
		System.out.println( "Sending Dicfile to " + socket.getRemoteSocketAddress().toString() );
		out.println( ( new Message( Message.Command.GET, Message.Keyword.UP, "DIC" ) ).toString() );
		out.flush();
		try {
			PrintStream ps = new PrintStream( socket.getOutputStream() );
			String XML = DicFile.XMLFromDicFile( dicFile );
			ps.println( XML );
//			sr.close();
		}
		catch ( Exception e ) {
			e.printStackTrace();
		}
	}
}
